/*
 * CPU.h
 *
 *  Created on: Nov 29, 2012
 *      Author: EklipZ
 */

#ifndef GUARD_CPU
#define GUARD_CPU

/*
 * Forward declare CPU because it's circularly referenced by other classes.
 */
typedef struct cpu2 Cpu;

#include "../alu/bit_def.h"
#include "../alu/alu.h"
#include "../alu/registerset.h"
#include "../controller/controller.h"
#include "../memory/memory.h"

#define P_BIT_POS 15
#define Z_BIT_POS 14
#define N_BIT_POS 13
#define O_BIT_POS 12
#define C_BIT_POS 11

/*
 * The CPU type.
 */
struct cpu2
{
	Register PC;
	Register state; //flags PZNOC
	Bit stop_bit;
	Register IR;
	Alu *alu;
	int program_size;
	Memory *memory;
	RegisterSet *registerset;
	Controller *controller;
};

/*
 * Initializes a new CPU object.
 * memory: a reference to the memory bank.
 * reg_file: a reference to the register file.
 */
Cpu *new_cpu(Memory *memory, RegisterSet *reg_file);

/*
 * Gets this CPU's controller.
 * cpu: a pointer to the cpu being operated on.
 */
Controller *cpu_get_controller(Cpu *cpu);

/*
 * Reads and executes the next available instruction.
 * cpu: a pointer to the cpu being operated on.
 */
void cpu_perform_instruction(Cpu *cpu);

/*
 * Halts the CPU so that no more instructions will execute.
 * cpu: a pointer to the cpu being operated on.
 */
void cpu_halt(Cpu *cpu);

/*
 * Gets the current value of the program counter.
 * cpu: a pointer to the cpu being operated on.
 */
Register cpu_get_pc(Cpu *cpu);

/*
 * Sets the program counter.
 * cpu: a pointer to the cpu being operated on.
 */
void cpu_set_pc(Cpu *cpu, Register value);

/*
 * Gets the current value of the instruction register.
 * cpu: a pointer to the cpu being operated on.
 */
Register cpu_get_ir(Cpu *cpu);

/*
 * Sets the instruction register.
 * cpu: a pointer to the cpu being operated on.
 */
void cpu_set_ir(Cpu *cpu, Register value);

/*
 * Gets the current value of the PSR register.
 * cpu: a pointer to the cpu being operated on.
 */
Register cpu_get_state(Cpu *cpu);

/*
 * Sets the PSR register.
 * cpu: a pointer to the cpu being operated on.
 * value: the new PSR value.
 */
void cpu_set_state(Cpu *cpu, Register value);

/*
 * Sign-extends a value.
 * value: The value that needs to be sign extended.
 * bit_mask: The bitmask of the bits in the register that are being used. The
 * remaining bits will be used for the sign extension.
 */
Register sign_extend(Register value, Register bit_mask);

/*
 * Frees the memory associated with this cpu.
 * cpu: a pointer to the cpu being operated on.
 */
void free_cpu(Cpu *cpu);

#endif
